﻿using System;
using System.Data;
using System.Configuration;
using SyCODE.Component.DataFactory;
using System.Xml;
using System.Web;
using System.IO;
using System.Text;
using System.Reflection;
using System.Threading;
using System.Data.Common;
using SyCODE.Component;

namespace SyCODE.Blog
{

    /// <summary>
    /// MainUpdate 的摘要说明
    /// 作用：定时更新首页内容
    /// </summary>
    public class MainUpdater
    {
        private struct SiteInfo
        {
            internal string Title;
            internal string Keywords;
            internal string Description;
        }

        private static SiteInfo siteInfo;
        /// <summary>
        /// 常驻线程
        /// </summary>
        private static Thread worker;

        /// <summary>
        /// 开始线程
        /// </summary>
        public static void Start()
        {
            siteInfo = new SiteInfo();
            XmlDocument tidyup = new XmlDocument();
            tidyup.Load(Path.Combine(AppPath.GetAppRootPath(), "tidyup.xml"));
            XmlNode head = tidyup.DocumentElement.SelectSingleNode("head");
            siteInfo.Title = head.SelectSingleNode("title").InnerText + " - Powered By X3BLOG";
            siteInfo.Keywords = head.SelectSingleNode("meta[@name='keywords']").Attributes["content"].Value;
            siteInfo.Description = head.SelectSingleNode("meta[@name='description']").Attributes["content"].Value;


            worker = new Thread(new ThreadStart(WorkerHandler));
            worker.IsBackground = false;
            worker.Priority = ThreadPriority.BelowNormal;
            worker.Start();
        }

        /// <summary>
        /// 线程的执行方法
        /// </summary>
        private static void WorkerHandler()
        {
            while (true)
            {
                Thread.Sleep(900000);
                XmlTextWriter writer = new XmlTextWriter(new MemoryStream(), Encoding.UTF8);

                DBAM dbam = new DBAM();
                try
                {
                    dbam.BuildParameters("mainupdate", null);

                    writer.WriteStartDocument();
                    writer.WriteProcessingInstruction("xml-stylesheet", "type='text/xsl' href='/ui/common/mainpage.xsl'");
                    writer.WriteStartElement("html");

                    WriteHead(writer);
                    WriteBody(writer, dbam.ExecuteReader());

                    writer.WriteEndElement();
                    writer.WriteEndDocument();
                    writer.Flush();

                    WriteToFile(writer.BaseStream);
                }
                finally
                {
                    writer.Close();
                    dbam.Dispose();
                }
            }
        }

        /// <summary>
        /// 写入文件头
        /// </summary>
        /// <param name="writer">XML编写器</param>
        private static void WriteHead(XmlTextWriter writer)
        {
            writer.WriteStartElement("head");

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("http-equiv", "Content-Type");
            writer.WriteAttributeString("content", "text/html; charset=utf-8");
            writer.WriteEndElement();

            writer.WriteStartElement("title");
            writer.WriteString(siteInfo.Title);
            writer.WriteEndElement();

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("name", "robots");
            writer.WriteAttributeString("content", "noodp");
            writer.WriteEndElement();

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("name", "keywords");
            writer.WriteAttributeString("content", siteInfo.Keywords);
            writer.WriteEndElement();

            writer.WriteStartElement("meta");
            writer.WriteAttributeString("name", "description");
            writer.WriteAttributeString("content", siteInfo.Description);
            writer.WriteEndElement();

            writer.WriteEndElement();
        }

        /// <summary>
        /// 写入内容项
        /// </summary>
        /// <param name="writer">XML编写器</param>
        /// <param name="dr">只进数据源</param>
        private static void WriteBody(XmlTextWriter writer, DbDataReader dr)
        {
            writer.WriteStartElement("body");

            writer.WriteStartElement("a");
            writer.WriteAttributeString("href", "/tidyup.xml");
            writer.WriteString("tidyup");
			writer.WriteEndElement();

			writer.WriteStartElement("a");
			writer.WriteAttributeString("href", "/index.aspx");
			writer.WriteString("Topic Index");
			writer.WriteEndElement();

            do
            {
                writer.WriteStartElement("p");
                while (dr.Read())
                {
                    writer.WriteStartElement("a");
                    writer.WriteAttributeString("href", HttpUtility.HtmlEncode(dr.GetString(0)).Replace("+", "%2b"));
                    writer.WriteAttributeString("id", dr.GetString(1));
                    writer.WriteAttributeString("name", dr.GetString(2));
                    writer.WriteString(dr.GetString(3));
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            } while (dr.NextResult());

            writer.WriteEndElement();
            dr.Close();
        }

        /// <summary>
        /// 更新到静态文件
        /// </summary>
        /// <param name="stream">内存流</param>
        private static void WriteToFile(Stream stream)
        {
            string path = Path.Combine(AppPath.GetAppRootPath(), "main.xml");
            FileStream fs = File.Create(path, 4096, FileOptions.SequentialScan);

            int bLen = 4096, cLen = 0;
            byte[] buffer = new byte[bLen];

            stream.Position = 0;
            while ((cLen = stream.Read(buffer, 0, bLen)) > 0)
            {
                fs.Write(buffer, 0, cLen);
            }
            fs.Flush();
            fs.Close();
        }
    }
}